package com.xtaller.lazy.api.base;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xtaller.lazy.base.TApi;
import com.xtaller.lazy.lib.R;
import com.xtaller.lazy.lib.annotation.Permission;
import com.xtaller.lazy.lib.convert.*;
import com.xtaller.lazy.lib.kit.MD5Util;
import com.xtaller.lazy.model.base.User;
import com.xtaller.lazy.model.base.UserRole;
import com.xtaller.lazy.model.system.Role;
import com.xtaller.lazy.model.system.UserJwt;
import com.xtaller.lazy.parameter.DocIds;
import com.xtaller.lazy.parameter.DocUser;
import com.xtaller.lazy.service.base.UserRoleService;
import com.xtaller.lazy.service.base.UserService;
import com.xtaller.lazy.service.system.RoleService;
import com.xtaller.lazy.service.system.UserJwtService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-04-10
 * @Description: 用户管理
 */
@Api(tags = "用户管理api")
@RestController
@RequestMapping("/v1/base")
public class UserApi extends TApi {
    @Autowired private UserService userService;
    @Autowired private UserRoleService userRoleService;
    @Autowired private RoleService roleService;
    @Autowired private UserJwtService jwtService;

    private Map<String, String> baseVerify() {
        var verify = M.create("loginName", "登录名不能为空")
                        .put("password", "登录密码不能为空");
        return verify;
    }

    @GetMapping("/user")
    @ApiOperation("读取数据")
    @Permission(authorities = "base-user-table")
    public Object table(@ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                        @ApiParam("页长") @RequestParam(value = "limit", required = false, defaultValue = "12") int limit,
                        @ApiParam("关键字") @RequestParam(value = "key", required = false, defaultValue = "") String key){
        var p = new Page<User>(page, limit);
        var qw = new QueryWrapper<User>();
        qw.lambda().select(
                User::getId, User::getLoginName, User::getTrueName,
                User::getNickName, User::getAvatar, User::getSex,
                User::getPhone, User::getEmail, User::getState)
                .orderByDesc(User::getCreateTime);

        if(!V.isEmpty(key)){
            qw.lambda().or(x -> x.like(User::getLoginName, key)
                                    .or().like(User::getPhone, key)
                                    .or().like(User::getEmail, key));
        }
        var pages = userService.page(p, qw);
        var users = J.o2l(pages.getRecords());
        var data = p2t(pages);
        // 处理角色信息

        if(users.size() > 0){
            List<UserRole> urs = new ArrayList<>();
            List<Role> rs = new ArrayList<>();
            users.forEach(u -> {
                u.put("role", J.list());
            });

            // 读取用户
            var uids = users.stream()
                    .map(x -> x.getLong("id"))
                    .distinct()
                    .collect(Collectors.toList());
            if(uids.size() > 0) {
                var urQw = new QueryWrapper<UserRole>();
                urQw.in("userId", uids);
                urs = userRoleService.list(urQw);
            }
            // 读取角色
            var rids = urs.stream()
                    .map(x -> x.getRoleId())
                    .distinct()
                    .collect(Collectors.toList());
            if(rids.size() > 0) {
                rs = roleService.listByIds(rids);
            }

            List<Role> finalRs = rs;
            List<UserRole> finalUrs = urs;
            users.forEach(u -> {
                u.put("role", formatRoleByUserId(finalRs, finalUrs, u.getLong("id")));
            });
            data.put("data", users);
        }
        return data;
    }
    /**
     *
     * 处理角色信息
     * */
    private List<JSONObject> formatRoleByUserId(List<Role> rs,List<UserRole> userRoles, Long userId){
        var list = J.list();
        if(rs.size() > 0 && userRoles.size() > 0) {
            // 读取用户关联的角色
            var urs = userRoles.stream().filter(x -> x.getUserId().equals(userId)).collect(Collectors.toList());
            // 处理数据
            urs.forEach(n -> {
                var obj = rs.stream().filter(
                        x -> x.getId().equals(n.getRoleId())).findFirst();
                list.add(J.create("id", obj.get().getId())
                        .put("name", obj.get().getName()));
            });
        }
        return list;
    }


    @PostMapping("/user")
    @ApiOperation("创建数据")
    @Permission(authorities = "base-user-create")
    public Object create(@ApiParam("数据对象") @RequestBody DocUser object){
        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString("message"));
        }
        // 唯一性判断
        var qw = new QueryWrapper<User>();
        qw.lambda().eq(User::getLoginName, object.getLoginName());
        var only = userService.list(qw);
        if(only.size() > 0) {
            return R.error("登录名已经存在");
        }

        var model = J.o2m(object, User.class);
        model.setCreateId(userId.get());
        // 密码处理
        var salt = S.random(6);
        var password = MD5Util.encode(S.apppend(model.getPassword(), salt));
        model.setPassword(password);
        model.setSalt(salt);

        model = userService.model(model);
        if(model == null) {
            return R.error("数据创建失败");
        }
        return R.ok("数据创建成功", model);
    }

    @PutMapping("/user/{id}")
    @ApiOperation("修改数据")
    @Permission(authorities = "base-user-update")
    public Object update(@ApiParam("数据id") @PathVariable Long id, @ApiParam("数据对象") @RequestBody DocUser object){
        var model = userService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        // 唯一性判断
        var qw = new QueryWrapper<User>();
        qw.lambda().eq(User::getLoginName, object.getLoginName())
                .ne(User::getId, id);
        var only = userService.list(qw);
        if(only.size() > 0) {
            return R.error("登录名已经存在");
        }
        model = J.o2m(object, User.class);
        model.setId(id);
        model.setUpdateId(userId.get());

        model = userService.model(model);
        if(model == null) {
            return R.error("数据修改失败");
        }
        return R.ok("数据修改成功", model);
    }

    @DeleteMapping("/user/{id}")
    @ApiOperation("删除数据")
    @Permission(authorities = "base-user-delete")
    public Object delete(@ApiParam("数据id") @PathVariable Long id){
        var model = userService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        if(userService.removeById(id)) {
            return R.ok("数据删除成功", J.create("id", id));
        }
        return R.error("数据删除失败");
    }

    @PutMapping("/user/state/{id}")
    @ApiOperation("调整状态")
    @Permission(authorities = "base-user-state")
    public Object state(@ApiParam("数据id") @PathVariable Long id){
        var model = userService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        var state = model.getState() == 0 ? 1 : 0;
        model.setState(state);

        model = userService.model(model);
        if(model != null) {
            if(state == 1){
                cleanJwt(id, 0);
            }
            return R.ok("数据状态成功", model);
        }else {
            return R.error("数据状态失败");
        }
    }

    @PutMapping("/user/pwd/{id}/{platform}")
    @ApiOperation("重置密码")
    @Permission(authorities = "base-user-pwd")
    public Object pwd(@ApiParam("数据id") @PathVariable Long id, @ApiParam("平台id") @PathVariable int platform){
        var model = userService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        // 密码处理
        var salt = S.random(6);
        var pwd = S.random(6);
        var password = MD5Util.encode(S.apppend(pwd, salt));
        model.setPassword(password);
        model.setSalt(salt);

        cleanJwt(id, platform);
        model = userService.model(model);
        if(model != null) {
            return R.ok("重置成功请牢记[ " + pwd + " ]", model);
        }
        return R.error("重置失败");
    }

    @PutMapping("/user/role/{id}")
    @ApiOperation("配置用户角色")
    @Permission(authorities = "base-user-role")
    public Object role(@ApiParam("数据id") @PathVariable Long id, @ApiParam("id数据") @RequestBody List<DocIds> ids){
        var model = userService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        if(ids.size() == 0){
            if(userRoleService.init(id)) {
                return R.ok("角色撤销成功", J.create("id", id));
            }else {
                return R.error("角色撤销失败");
            }
        }

        var urs = new ArrayList<UserRole>();
        ids.stream().forEach(x -> {
            var ur = new UserRole();
            ur.setRoleId(x.getValue());
            ur.setUserId(id);
            urs.add(ur);
        });

        if(userRoleService.setRole(urs, id)) {
            return R.ok("角色分配成功");
        }else {
            return R.error("角色分配失败");
        }
    }

    /**
     * 当重置密码 冻结用户时候 则需要清空用户的jwt信息
     * */
    private void cleanJwt(Long userId, int platform){
        var uj = new UserJwt();
        uj.setJwt("");
        var qw = new QueryWrapper<UserJwt>();
        qw.lambda().eq(UserJwt::getUserId, userId);
        if(platform != 0){
            qw.lambda().eq(UserJwt::getPlatform, platform);
        }
        jwtService.update(uj, qw);
    }
}
